﻿using System.Collections;
using System.Data;
using System.Data.SqlClient;
using System.Web;
using System.Web.Security;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.Data.Sql;

namespace ASPNETVN.PORTAL.Components.Security
{
    public class PortalSecurity
    {
        public static PortalPrincipal CurrentUser
        {
            get
            {
                PortalPrincipal r;

                if (HttpContext.Current.User is PortalPrincipal)
                    r = (PortalPrincipal)HttpContext.Current.User;

                else
                    r = new PortalPrincipal(HttpContext.Current.User.Identity, null);
                return r;
            }

            set
            {
                HttpContext.Current.User = value;
            }
        }

        public static string Encrypt(string str)
        {
            return FormsAuthentication.HashPasswordForStoringInConfigFile(str, "SHA1");
        }

        public static bool IsInRole(string role)
        {
            return CurrentUser.IsInRole(role);
        }

        public static bool IsInRoles(string roles)
        {
            //PortalSecurity.CurrentUser.Identity.PortalID
            foreach (string role in roles.Split(';'))
            {
                if (role != null)
                {
                    // -1: All Users.
                    if (role.Trim() != string.Empty && ((role.Trim() == "-1") || (IsInRole(role.Trim()))))
                    {
                        return true;
                    }
                    // -2: Authenticated Users.
                    if ((role.Trim() == "-2") && (HttpContext.Current.Request.IsAuthenticated))
                    {
                        return true;
                    }
                    // -3: Unauthenticated Users.
                    if ((role.Trim() == "-3") && (!HttpContext.Current.Request.IsAuthenticated))
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        public static void AccessDenied()
        {
            string returnUrl = HttpContext.Current.Server.UrlEncode(HttpContext.Current.Request.RawUrl);
            HttpContext.Current.Response.Redirect("~/SignIn.aspx?returnUrl=" + returnUrl);
        }

        public static void AccessEditDenied()
        {
            string returnUrl = HttpContext.Current.Server.UrlEncode(HttpContext.Current.Request.RawUrl);
            HttpContext.Current.Response.Redirect("~/SignIn.aspx?returnUrl=" + returnUrl);
        }

        public static bool HasViewAuthorization(int moduleID)
        {
            // Administrators Role.
            if (PortalSecurity.IsInRole("1")) return true;

            PortalDataSet ds = (PortalDataSet)HttpContext.Current.Items["PortalDataSet"];
            PortalDataSet.ModuleRow moduleRow = ds.Module.FindByID(moduleID);
            string viewRoles = moduleRow.AuthorizedViewRoles;
            string accessRoles = moduleRow.TabRow.AuthorizedRoles;
            if (IsInRoles(accessRoles) == false || IsInRoles(viewRoles) == false)
                return false;
            return true;
        }

        public static bool HasAddAuthorization(int moduleID)
        {
            // Administrators Role.
            if (PortalSecurity.IsInRole("1")) return true;

            PortalDataSet ds = (PortalDataSet)HttpContext.Current.Items["PortalDataSet"];
            PortalDataSet.ModuleRow moduleRow = ds.Module.FindByID(moduleID);
            string addRoles = moduleRow.AuthorizedAddRoles;
            string accessRoles = moduleRow.TabRow.AuthorizedRoles;
            if (IsInRoles(accessRoles) == false || IsInRoles(addRoles) == false)
                return false;
            return true;
        }

        public static bool HasEditAuthorization(int moduleID)
        {
            // Administrators Role.
            if (PortalSecurity.IsInRole("1")) return true;

            PortalDataSet ds = (PortalDataSet)HttpContext.Current.Items["PortalDataSet"];
            PortalDataSet.ModuleRow moduleRow = ds.Module.FindByID(moduleID);
            string editRoles = moduleRow.AuthorizedEditRoles;
            string accessRoles = moduleRow.TabRow.AuthorizedRoles;
            if (IsInRoles(accessRoles) == false || IsInRoles(editRoles) == false)
                return false;
            return true;
        }

        public static bool HasDeleteAuthorization(int moduleID)
        {
            // Administrators Role.
            if (PortalSecurity.IsInRole("1")) return true;

            PortalDataSet ds = (PortalDataSet)HttpContext.Current.Items["PortalDataSet"];
            PortalDataSet.ModuleRow moduleRow = ds.Module.FindByID(moduleID);
            string deleteRoles = moduleRow.AuthorizedDeleteRoles;
            string accessRoles = moduleRow.TabRow.AuthorizedRoles;
            if (IsInRoles(accessRoles) == false || IsInRoles(deleteRoles) == false)
                return false;
            return true;
        }

        public static bool HasSettingAuthorization(int moduleID)
        {
            // Administrators Role.
            if (PortalSecurity.IsInRole("1")) return true;

            PortalDataSet ds = (PortalDataSet)HttpContext.Current.Items["PortalDataSet"];
            PortalDataSet.ModuleRow moduleRow = ds.Module.FindByID(moduleID);
            string settingRoles = moduleRow.AuthorizedSettingRoles;
            string accessRoles = moduleRow.TabRow.AuthorizedRoles;
            if (IsInRoles(accessRoles) == false || IsInRoles(settingRoles) == false)
                return false;
            return true;
        }

        public static bool HasManagerAuthorization(int moduleID)
        {
            // Administrators Role.
            if (PortalSecurity.IsInRole("1")) return true;

            PortalDataSet ds = (PortalDataSet)HttpContext.Current.Items["PortalDataSet"];
            PortalDataSet.ModuleRow moduleRow = ds.Module.FindByID(moduleID);
            string managerRoles = moduleRow.AuthorizedManagerRoles;
            string accessRoles = moduleRow.TabRow.AuthorizedRoles;
            if (IsInRoles(accessRoles) == false || IsInRoles(managerRoles) == false)
                return false;
            return true;
        }

        public static bool HasSecurityAuthorization(int moduleID)
        {
            // Administrators Role.
            if (PortalSecurity.IsInRole("1")) return true;

            PortalDataSet ds = (PortalDataSet)HttpContext.Current.Items["PortalDataSet"];
            PortalDataSet.ModuleRow moduleRow = ds.Module.FindByID(moduleID);
            string securityRoles = moduleRow.AuthorizedSecurityRoles;
            string accessRoles = moduleRow.TabRow.AuthorizedRoles;
            if (IsInRoles(accessRoles) == false || IsInRoles(securityRoles) == false)
                return false;
            return true;
        }

        public static bool HasSpecialAuthorization(int moduleID, string functionID, string[] functions)
        {
            // Administrators Role.
            if (PortalSecurity.IsInRole("1")) return true;

            foreach (string f in functions)
            {
                if (functionID.ToUpper().Trim() == f.ToUpper().Trim())
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Lấy danh sách các chức năng trong module của user hiện tại.
        /// </summary>
        /// <param name="moduleID">Module ID</param>
        /// <returns>Danh sách các chức năng trong module của user hiện tại.</returns>
        public static string[] SelectFunctionBy_CurrentUser(int moduleID)
        {
            const string spName = "p_SYSTEM_Permission_SelectFunctionBy_UserID_ModuleID";

            SqlDatabase db = (SqlDatabase)DatabaseFactory.CreateDatabase();
            SqlCommand dbCommand = (SqlCommand)db.GetStoredProcCommand(spName);
            db.AddInParameter(dbCommand, "@UserID", SqlDbType.Int, CurrentUser.Identity.ID);
            db.AddInParameter(dbCommand, "@ModuleID", SqlDbType.Int, moduleID);

            IDataReader reader = db.ExecuteReader(dbCommand);

            ArrayList functions = new ArrayList();
            while (reader.Read())
            {
                functions.Add(reader["FunctionID"].ToString());
            }
            reader.Close();
            dbCommand.Connection.Close();
            return (string[])functions.ToArray(typeof(string));
        }

        public static string[] SelectFunctionBy_RoleID_ModuleID(int roleID, int moduleID)
        {
            const string spName = "p_SYSTEM_Permission_SelectFunctionBy_RoleID_ModuleID";

            SqlDatabase db = (SqlDatabase)DatabaseFactory.CreateDatabase();
            SqlCommand dbCommand = (SqlCommand)db.GetStoredProcCommand(spName);
            db.AddInParameter(dbCommand, "@RoleID", SqlDbType.Int, roleID);
            db.AddInParameter(dbCommand, "@ModuleID", SqlDbType.Int, moduleID);

            IDataReader reader = db.ExecuteReader(dbCommand);

            ArrayList functions = new ArrayList();
            while (reader.Read())
            {
                functions.Add(reader["FunctionID"].ToString());
            }
            reader.Close();
            dbCommand.Connection.Close();
            return (string[])functions.ToArray(typeof(string));
        }

        public static void UpdatePermissions(int roleID, int moduleID, string[] functions)
        {
            SqlDatabase db = (SqlDatabase)DatabaseFactory.CreateDatabase();
            using (SqlConnection connection = (SqlConnection)db.CreateConnection())
            {
                connection.Open();
                SqlTransaction transaction = connection.BeginTransaction();
                try
                {
                    Permission.Delete(transaction, roleID, moduleID);
                    foreach (string f in functions)
                    {
                        Permission.Insert(transaction, roleID, moduleID, f);
                    }
                    transaction.Commit();
                }
                catch
                {
                    transaction.Rollback();
                }
                finally
                {
                    connection.Close();
                }
            }
        }
    }
}